#!/usr/bin/env python3

# Copyright (c) 2020-2021 Fpemud <fpemud@sina.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.


import re
from ._errors import FileFormatError


class Handy:

    VALID_KEY_TYPES = [
        "rsa",
        "ecdsa",
        "ed25519",
    ]

    KEY_TYPE_MAPPING = {
        "ssh-rsa": "rsa",
        "ecdsa-sha2-nistp256": "ecdsa",
        "ecdsa-sha2-nistp384": "ecdsa",
        "ecdsa-sha2-nistp521": "ecdsa",
        "ssh-ed25519": "ed25519",
    }

    COMMON_ENV_LIST = [
        "TERM",
        "LANG",
        "LC_*",
    ]

    @staticmethod
    def lineListReSearch(lineList, pattern, flags=0):
        assert flags == 0 or re.M not in flags
        ret = None
        for line in lineList:
            m = re.search(pattern, line, flags)
            if m is not None:
                if ret is not None:
                    raise FileFormatError("duplicate directive found")
                ret = m
        return ret

    @staticmethod
    def lineListReSearchMulti(lineList, pattern, flags=0):
        assert flags == 0 or re.M not in flags
        ret = []
        for line in lineList:
            m = re.search(pattern, line, flags)
            if m is not None:
                ret.append(m)
        return ret

    @staticmethod
    def lineListRemoveLines(lineList, pattern):
        ret = False
        for i in reversed(range(0, len(lineList))):
            if re.search(pattern, lineList[i]) is not None:
                lineList.pop(i)
                ret = True
        return ret

    @staticmethod
    def lineListReplaceOrAddLine(lineList, pattern, newLine):
        ret = []
        for i, line in enumerate(lineList):
            if re.search(pattern, line) is not None:
                ret.append(i)

        if len(ret) == 0:
            if newLine is None:
                return False
            else:
                lineList.append(newLine)
                return True

        if len(ret) == 1:
            if newLine is not None:
                if lineList[ret[0]] == newLine:
                    return False
                else:
                    lineList[ret[0]] = newLine
                    return True
            else:
                lineList.pop(ret[0])
                return True

        raise FileFormatError("duplicate directive found")

    @staticmethod
    def yn2bool(s, directive, bOnOff=False):
        if bOnOff:
            yStr = ["on", "yes", "true"]
            nStr = ["off", "no", "false"]
        else:
            yStr = ["yes", "true"]
            nStr = ["no", "false"]

        if s in yStr:
            return True
        elif s in nStr:
            return False
        else:
            raise FileFormatError("invalid value \"%s\" for %s directive" % (s, directive))

    @staticmethod
    def bool2(t, value):
        if t == "yn":
            return "yes" if value else "no"
        elif t == "tf":
            return "true" if value else "false"
        elif t == "on-off":
            return "on" if value else "off"
        else:
            assert False
